﻿/* Copyright 2007-2008 dnAnalytics Project.
 *
 * Contributors to this file:
 * Jurgen Van Gael
 *
 * This file is part of dnAnalytics.  dnAnalytics is licensed under the 
 * Microsoft Public License. See License.txt for a complete copy of the
 * license.
 */

using System;

namespace dnAnalytics.Statistics.Distributions
{
    /// <summary>
    /// The Delta distribution is a distribution over the real numbers that peaks at one
    /// particular value.
    /// </summary>
    /// <remarks>The distribution will use the <see cref="System.Random"/> by default. 
    /// Users can set the random number generator by using the <see cref="RandomNumberGenerator"/> property.
    /// 
    /// The statistics classes will check all the incoming parameters whether they are in the allowed
    /// range. This might involve heavy computation. Optionally, by setting Control.CheckDistributionParameters
    /// to false, all parameter checks can be turned off.</remarks>
    public class Delta : IContinuousDistribution
    {
        // The location of the delta peak.
        private readonly double mLocation;

        /// <summary>
        /// Constructs a standard normal (mean = 0, standard deviation = 1).
        /// </summary>
        public Delta(double loc)
        {
            if (Control.CheckDistributionParameters)
            {
                CheckParameters(loc);
            }

            mLocation = loc;
            RandomNumberGenerator = new System.Random();
        }

        /// <summary>
        /// Checks the parameters of a delta distribution.
        /// </summary>
        /// <param name="loc">The location of the delta peak.</param>
        /// <exception cref="ArgumentOutOfRangeException">If the delta peak is NaN.</exception>
        private static void CheckParameters(double loc)
        {
            if (double.IsNaN(loc))
            {
                throw new ArgumentOutOfRangeException("loc", "Location is NaN.");
            }
        }

        #region IDistribution Members

        /// <summary>
        /// Gets the mean of the distribution.
        /// </summary>
        /// <value>The mean of the distribution.</value>
        public double Mean
        {
            get { return mLocation; }
        }

        /// <summary>
        /// Gets the standard deviation of the distribution.
        /// </summary>
        /// <value>The standard deviation of the distribution.</value>
        public double StdDev
        {
            get { return 0.0; }
        }

        /// <summary>
        /// Gets the variance of the distribution.
        /// </summary>
        /// <value>The variance of the distribution.</value>
        public double Variance
        {
            get { return 0.0; }
        }

        /// <summary>
        /// The entropy of the distribution.
        /// </summary>
        /// <value></value>
        public double Entropy
        {
            get { return 0.0; }
        }

        /// <summary>
        /// Gets or sets the random number generator.
        /// </summary>
        /// <value>The random number generator used to generate a random sample.</value>
        public System.Random RandomNumberGenerator { get; set; }

        #endregion

        #region IContinuousDistribution Members

        /// <summary>
        /// The mode of the distribution.
        /// </summary>
        /// <value></value>
        public double Mode
        {
            get { return mLocation; }
        }

        /// <summary>
        /// The median of the distribution.
        /// </summary>
        /// <value></value>
        public double Median
        {
            get { return mLocation; }
        }

        /// <summary>
        /// Evaluates the probability density function for a the normal distribution.
        /// </summary>
        public double Density(double x)
        {
            return x == mLocation ? double.PositiveInfinity : 0.0;
        }

        /// <summary>
        /// Samples draws a random sample for the distribution.
        /// </summary>
        /// <returns>A random number from this distribution.</returns>
        public double Sample()
        {
            return mLocation;
        }

        /// <summary>
        /// Samples an array of normal distributed random variables.
        /// </summary>
        /// <param name="size">The number of variables needed.</param>
        /// <returns>An array of random numbers from this distribution.</returns>
        public double[] Sample(int size)
        {
            double[] s = new double[size];
            for (int i = 0; i < size; i++)
            {
                s[i] = mLocation;
            }
            return s;
        }

        #endregion

        /// <summary>
        /// Evaluates the cumulative distribution function for the delta distribution.
        /// </summary>
        public double CumulativeDistribution(double x)
        {
            return x < mLocation ? 0.0 : 1.0;
        }
    }
}